package com.im

import android.annotation.SuppressLint
import android.content.Intent
import android.content.res.Resources
import android.graphics.BitmapFactory
import android.os.Bundle
import android.text.TextUtils

import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout

import com.im.ui.theme.ImClientTheme

import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

// 聊天活动
class ChatActivity: AppCompatActivity() {
    // 聊天表项
    class ChatListItem(val icon: ImageBitmap, val text: String, val isLeft: Boolean, val time: String)

    private lateinit var mInputText: MutableState<String>   // 用户输入的文字
    private lateinit var mScrollState: LazyListState        // 滚动状态

    companion object {
        private val sChatList = mutableStateMapOf<String, MutableList<ChatListItem>>()  // 与所有好友的全部聊天内容
        private var sItems: SnapshotStateList<ChatListItem>? = null                     // 与当前好友的全部聊天内容

        /**
         * 添加好友。
         * @param friendName    好友名
         */
        fun addFriend(friendName: String) {
            if (sChatList[friendName] == null) {
                sChatList[friendName] = mutableListOf()
            }
        }

        /**
         * 添加一个表项。
         * @param friendName    好友名
         * @param chatInfo      聊天信息
         * @param resources     资源
         */
        private fun addItem(friendName: String, chatInfo: ChatInfo?, resources: Resources) {
            if (chatInfo == null) {
                return
            }
            val isLeft = Client.username != chatInfo.mSrcUsername
            val icon = BitmapFactory.decodeResource(resources, chatInfo.mSrcIconIndex + R.mipmap.normal00).asImageBitmap()
            val item = ChatListItem(icon, chatInfo.mContent, isLeft, chatInfo.mTime)
            sChatList[friendName]?.add(item)
        }

        /**
         * 清除聊天内容。
         */
        fun clear() {
            sItems?.clear()
            sChatList.clear()
        }

        /**
         * 获取好友名。
         */
        var friendName = ""
            private set
    }

    /**
     * 添加一个表项。
     * @param chatInfo  聊天信息
     */
    fun addItem(chatInfo: ChatInfo?) {
        if (chatInfo == null) {
            return
        }
        val isLeft = Client.username != chatInfo.mSrcUsername
        val icon = BitmapFactory.decodeResource(resources, chatInfo.mSrcIconIndex + R.mipmap.normal00).asImageBitmap()
        val item = ChatListItem(icon, chatInfo.mContent, isLeft, chatInfo.mTime)
        sItems?.add(item)
        sChatList[friendName]?.add(item)
        this.scrollToBottom()
    }

    /**
     * 界面布局。
     */
    @Composable
    fun Greeting() {
        // 初始化成员
        mInputText = remember {
            mutableStateOf("")
        }
        mScrollState = rememberLazyListState()
        sItems = remember {
            mutableStateListOf()
        }
        if (sItems!!.isEmpty()) {
            var username = intent.getStringExtra(Const.KEY_FRIEND_NAME)
            sItems!!.addAll(sChatList[username]!!)
            this.scrollToBottom()
        }

        val maxItemWidth = LocalConfiguration.current.screenWidthDp.dp - Const.CHAT_ACTIVITY_CTRL_PADDING * 4
        val iconWidth = BitmapFactory.decodeResource(resources, R.mipmap.normal00).width / LocalDensity.current.density
        val maxTextWidth = maxItemWidth - iconWidth.dp * 2

        // 布局
        ConstraintLayout(Modifier.fillMaxSize()) {
            val (listViewChat, editInput) = this.createRefs()

            // 聊天历史控件
            LazyColumn(Modifier
                .fillMaxSize()
                .padding(
                    top = Const.CHAT_ACTIVITY_LIST_EDIT_PADDING,
                    bottom = Const.CHAT_ACTIVITY_LIST_EDIT_PADDING
                )
                .constrainAs(listViewChat) {
                    start.linkTo(parent.start)
                    top.linkTo(parent.top)
                    bottom.linkTo(editInput.top)
                },
                mScrollState
            ) {
                itemsIndexed(sItems!!) { index, item ->
                    ConstraintLayout(Modifier.fillMaxWidth()) {
                        val (timeLabel, iconImage, chatText) = this.createRefs()
                        // 时间
                        Text(
                            text = item.time,
                            textAlign = TextAlign.Center,
                            color = Color.Gray,
                            modifier = Modifier
                                .fillMaxWidth()
                                .constrainAs(timeLabel) {
                                    start.linkTo(parent.start)
                                    top.linkTo(parent.top)
                                }
                        )
                        // 头像
                        Image(
                            bitmap = item.icon,
                            contentDescription = "",
                            modifier = Modifier
                                .padding(Const.CHAT_ACTIVITY_CTRL_PADDING)
                                .constrainAs(iconImage) {
                                    if (item.isLeft) {
                                        start.linkTo(parent.start)
                                    } else {
                                        end.linkTo(parent.end)
                                    }
                                    top.linkTo(timeLabel.bottom)
                                }
                        )
                        // 聊天内容
                        Column(
                            modifier = Modifier
                                .padding(
                                    top = Const.CHAT_ACTIVITY_CTRL_PADDING,
                                    bottom = Const.CHAT_ACTIVITY_CTRL_PADDING * 2
                                )
                                .background(
                                    color = if (item.isLeft) Const.CHAT_ACTIVITY_LEFT_COLOR else Const.CHAT_ACTIVITY_RIGHT_COLOR,
                                    shape = RoundedCornerShape(Const.CHAT_ACTIVITY_CORNER_SIZE)
                                )
                                .constrainAs(chatText) {
                                    if (item.isLeft) {
                                        start.linkTo(iconImage.end)
                                    } else {
                                        end.linkTo(iconImage.start)
                                    }
                                    top.linkTo(iconImage.top)
                                },
                            verticalArrangement = Arrangement.Center
                        ) {
                            Text(
                                modifier = Modifier
                                    .padding(Const.CHAT_ACTIVITY_CTRL_PADDING)
                                    .widthIn(max = maxTextWidth),
                                text = item.text
                            )
                        }
                    }
                }
            }

            Row(Modifier
                .fillMaxWidth()
                .constrainAs(editInput) {
                    start.linkTo(parent.start)
                    bottom.linkTo(parent.bottom)
                }
            ) {
                // 输入聊天内容控件
                OutlinedTextField(
                    modifier = Modifier
                        .weight(0.7f)
                        .padding(
                            start = Const.CHAT_ACTIVITY_CTRL_PADDING,
                            end = Const.CHAT_ACTIVITY_CTRL_PADDING / 2
                        ),
                    value = mInputText.value,
                    onValueChange = {
                        if (it.length <= Const.MAX_CONTENT_LEN) {
                            mInputText.value = it
                        }
                    }
                )

                // 发送按钮
                Button(
                    onButtonSendClicked,
                    Modifier
                        .weight(0.3f)
                        .padding(
                            start = Const.CHAT_ACTIVITY_CTRL_PADDING / 2,
                            end = Const.CHAT_ACTIVITY_CTRL_PADDING
                        )
                        .focusable(false)
                ) {
                    Text(super.getString(R.string.IDS_SEND))
                }
            }
        }
    }

    /**
     * "发送"按钮的单击响应方法。
     */
    val onButtonSendClicked = fun() {
        if (TextUtils.isEmpty(mInputText.value.trim())) {
            return
        }

        // 获取当前时间
        val time = SimpleDateFormat(Const.DATE_TIME_FORMAT, Locale.getDefault()).format(Date())

        // 显示聊天内容
        val chatInfo = ChatInfo(mInputText.value, friendName, Client.iconIndex, Client.username, time)
        this.addItem(chatInfo)

        // 清空聊天内容编辑框
        mInputText.value = ""

        // 发送聊天内容
        val intent = Intent(Const.INTENT_CHAT_C2S)
        intent.putExtra(ChatInfo::class.java.name, chatInfo)
        super.sendBroadcast(intent)
    }

    /**
     * 创建事件的响应方法。
     * @param savedInstanceState    保存的实例状态
     */
    @SuppressLint("MissingSuperCall")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 设置内容
        this.setContent {
            ImClientTheme {
                this.Greeting()
            }
        }

        // 处理意图
        this.onGetIntent(super.getIntent())
    }

    /**
     * 处理接收到的意图。
     * @param intent    意图
     */
    private fun onGetIntent(intent: Intent) {
        // 获取好友名
        val friendName = intent.getStringExtra(Const.KEY_FRIEND_NAME)

        // 获取聊天信息
        val chatInfo = intent.getSerializableExtra(Const.KEY_CHAT_INFO) as ChatInfo?

        // 如果是当前好友，则显示聊天信息并返回
        if (friendName == Companion.friendName && chatInfo != null) {
            this.addItem(chatInfo)
            return
        }

        // 如果不是当前好友，则切换好友
        Companion.friendName = friendName!!

        // 获取好友名对应的聊天信息并加入新的聊天信息
        if (sItems != null) {
            // ChatActivity 在前台，直接添加聊天信息到界面上
            sItems!!.clear()
            sItems!!.addAll(sChatList[friendName]!!)
            this.addItem(chatInfo)
        } else {
            // ChatActivity 不在前台，将聊天信息添加到缓存中
            addItem(friendName, chatInfo, resources)
            this.scrollToBottom()
        }

        // 设置标题
        super.setTitle(friendName)
    }

    /**
     * 接收到新的意图的响应方法。
     * @param intent    意图
     */
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        this.onGetIntent(intent)
    }

    /**
     * 滚动到底部。
     */
    private fun scrollToBottom() {
        if (::mScrollState.isInitialized && sItems?.size!! > 1) {
            mScrollState.requestScrollToItem(sItems!!.size - 1)
        }
    }
}
